"""
This file contains various tests used during the generation of the 10-tetrahedra census 

The tests generally follow the following format:

INPUT: sg, a string representing the signature of the triangulation
OUTPUT: True or False, indicating whether the test gives an affirmative answer

Some tests have extra parameters as input, see Section 3.2 of the paper.
"""

import snappy, regina
# version of snappy used: 3.2
# version of regina used: 7.3

def greedy_nonminimality(sg):
    return regina.Triangulation3(sg).intelligentSimplify()

def certify_hyperbolicity(sg, r):
    m = snappy.Manifold(sg)
    if not m.is_orientable():
        m = m.orientation_cover()

    for i in range(r):
        m.randomize()

        try:
            if m.verify_hyperbolicity(bits_prec = 202)[0]:
                return True
        except:
            pass
    
    return False

def exhaustive_nonminimality(sg, h, threads = 8):
    # the function regina.Triangulation3.simplifyExhaustive supports multi-threads acceleration
    # the number of threads used is specified by the variable threads
    return regina.Triangulation3(sg).simplifyExhaustive(h, threads)

def special_surface(sg):
    t = regina.Triangulation3(sg)
    nss = regina.NormalSurfaces(t,regina.NS_STANDARD)

    for ns in nss:
        if ns.eulerChar() > 0:
            return True
    
        if ns.eulerChar() == 0 and not ns.isVertexLink():

            if not ns.isTwoSided():
                return True
            else:
                cut_t = ns.cutAlong()
                cut_t.intelligentSimplify()
                found = True

                for comp in cut_t.triangulateComponents():

                    if not comp.isOrientable():
                        comp.makeDoubleCover()
                    assert comp.isOrientable()
                    
                    comp.intelligentSimplify()
                    comp.knowsSolidTorus()

                    if not comp.isSolidTorus(): 
                        found = False
                        break
                
                if found:
                    return True

    return False